﻿using System.Collections.Generic;
using System.Dynamic;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using Newtonsoft.Json;

namespace AspnetUtil.Web.Filter.Auth
{
    /// <summary>
    /// jwt 内容
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class JwtClaim<T>
    {
        /// <summary>
        /// 用户的 id
        /// </summary>
        public T Uid { get; set; }
    }

    /// <summary>
    /// jwt 验证器
    /// </summary>
    public class JwtAuthentication
    {
        private const string Secret = "2fe7c0e8427c9d596508593c8ba60805";


        /// <summary>
        /// 生成 token
        /// </summary>
        /// <param name="uid"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static string GenToken<T>(T uid)
        {
            var payload = new JwtClaim<T>
            {
                Uid = uid
            };

            IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); // symmetric
            IJsonSerializer serializer = new JsonNetSerializer();
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);

            var token = encoder.Encode(payload, Secret);
            return token;
        }

        /// <summary>
        /// 解码 token 返回 <see cref="JwtClaim{T}"/>
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static JwtClaim<T> Decode<T>(string token)
        {
            IJsonSerializer serializer = new JsonNetSerializer();
            var provider = new UtcDateTimeProvider();
            IJwtValidator validator = new JwtValidator(serializer, provider);
            IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
            IJwtAlgorithm algorithm = new HMACSHA256Algorithm(); // symmetric
            IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);

            var json = decoder.Decode(token, Secret, verify: true);

            return JsonConvert.DeserializeObject<JwtClaim<T>>(json);
        }
    }
}